package com.sright.bcard.content.biz.manager.impl;

import com.sright.bcard.common.service.share.utils.DateTimeUtils;
import com.sright.bcard.common.service.share.utils.IpUtils;
import com.sright.bcard.common.service.share.utils.NumberUtils;
import com.sright.bcard.content.biz.manager.DataManager;
import com.sright.bcard.content.dal.dao.CardDAO;
import com.sright.bcard.content.dal.dao.DataCardShareNumDAO;
import com.sright.bcard.content.dal.dao.DataClickDAO;
import com.sright.bcard.content.dal.dao.UserDAO;
import com.sright.bcard.content.dal.entity.CardDO;
import com.sright.bcard.content.dal.entity.DataCardShareNumDO;
import com.sright.bcard.content.dal.entity.DataClickDO;
import com.sright.bcard.content.dal.entity.UserDO;
import com.sright.bcard.common.service.share.dto.content.DataResultDTO;
import com.sright.bcard.content.share.request.CountButtonParam;
import com.sright.bcard.user.dal.dao.*;
import com.sright.bcard.user.dal.entity.*;
import com.sright.common.response.SrightResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

@Component
@Slf4j
public class DataManagerImpl implements DataManager {
    @Autowired
    private DataCardShareNumDAO dataCardShareNumDAO;

    @Autowired
    private CardDAO cardDAO;

    @Autowired
    private UserDAO userDAO;

    @Autowired
    private DataClickDAO dataClickDAO;

    @Autowired
    private VisitorDateDAO visitorDateDAO;

    @Autowired
    private MemberDAO memberDAO;

    @Autowired
    private VisitorStatisticsDAO visitorStatisticsDAO;

    @Autowired
    private VisitorDAO visitorDAO;

    @Autowired
    private VisitorListDAO visitorListDAO;

    @Override
    public Boolean recordShareNum(Long cardId, Long userId) {
        DataCardShareNumDO dataCardShareNumDO = new DataCardShareNumDO();
        dataCardShareNumDO.setCardId(cardId);
        dataCardShareNumDO.setUserId(userId);
        SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy 00:00:00");
        try {
            dataCardShareNumDO.setCreatedAt(formatter.parse(formatter.format(new Date())));
        } catch (ParseException e) {
            e.printStackTrace();
        }

        DataCardShareNumDO dataCardShareNum = dataCardShareNumDAO.selectByObject(dataCardShareNumDO);
        if (dataCardShareNum == null) {
            dataCardShareNumDO.setNum(1);
            return dataCardShareNumDAO.insertSelective(dataCardShareNumDO) > 1;
        } else {
            dataCardShareNum.setNum(dataCardShareNum.getNum() + 1);
            return dataCardShareNumDAO.updateAll(dataCardShareNum);
        }
    }

    @Override
    public Long countClickOne(Long cardId, Long userId) {
        CardDO cardInfo = cardDAO.selectById(cardId);
        UserDO userInfo = userDAO.selectById(userId);
        VisitorDateDO visitorDateDO = new VisitorDateDO();
        visitorDateDO.setEnterpriseId(userInfo.getEnterpriseId());
        visitorDateDO.setUserId(userInfo.getId());
        visitorDateDO.setMemberId(userInfo.getMemberId());
        visitorDateDO.setType(5);
        SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
        try {
            visitorDateDO.setToday(formatter.parse(formatter.format(new Date())));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Long id = 0L;
        VisitorDateDO visitorDateDO1 = visitorDateDAO.selectByObject(visitorDateDO);
        if (visitorDateDO1 == null) {
            visitorDateDO.setTotal(1);
            id = visitorDateDAO.insertSelective(visitorDateDO);
        } else {
            visitorDateDO1.setTotal(visitorDateDO1.getTotal() + 1);
        }
        return id;
    }

    @Override
    public Long countClick(Long cardId, Integer type,Long memberId) {
        //判断名片属于个人还是企业
        if (cardId == null) {
            return 0L;
        }
        CardDO cardDO = cardDAO.selectById(cardId);
        DataClickDO dataClickDO = new DataClickDO();
        dataClickDO.setMemberId(memberId);
        dataClickDO.setCardId(cardId);
        dataClickDO.setType(type);
        if (cardDO.getEnterpriseId() > 0) {
            dataClickDO.setCardType(1);
        } else {
            //兼容老版本
            UserDO userDO = userDAO.selectById(cardDO.getUserId());
            if (userDO == null) {
                dataClickDO.setCardType(1);
            } else {
                if (userDO.getEnterpriseId() > 0) {
                    dataClickDO.setCardType(1);
                } else {
                    dataClickDO.setCardType(2);
                }
            }
        }

        return dataClickDAO.insertSelective(dataClickDO);
    }

    @Override
    public Boolean updateLoginTime(Long userId) {
        UserDO userDO = userDAO.selectById(userId);
        userDO.setLastLoginAt(new Date());
        return userDAO.updateSelective(userDO);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class)
    public Long countButton(CountButtonParam param, HttpServletRequest request) {
        //被访问人信息
        UserDO userInfo = userDAO.selectById(param.getCardUserId());
        if (userInfo.getMemberId().equals(param.getMemberId())) {
            return 0L;
        }

        VisitorDateDO visitorDateDO = new VisitorDateDO();
        visitorDateDO.setEnterpriseId(userInfo.getEnterpriseId());
        visitorDateDO.setUserId(userInfo.getId());
        visitorDateDO.setMemberId(userInfo.getMemberId());
        visitorDateDO.setType(param.getType());
        SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
        try {
            visitorDateDO.setToday(formatter.parse(formatter.format(new Date())));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Long visitorDateId;
        VisitorDateDO visitorDateDO1 = visitorDateDAO.selectByObject(visitorDateDO);
        if (visitorDateDO1 == null) {
            visitorDateDO.setTotal(1);
            visitorDateId = visitorDateDAO.insert(visitorDateDO);
        } else {
            visitorDateDO1.setTotal(visitorDateDO1.getTotal() + 1);
            visitorDateId = visitorDateDO1.getId();
        }

        MemberDO memberDO = memberDAO.selectById(param.getMemberId());
        VisitorStatisticsDO visitorStatisticsDO = new VisitorStatisticsDO();
        visitorStatisticsDO.setEnterpriseId(userInfo.getEnterpriseId());
        visitorStatisticsDO.setToUserId(userInfo.getId());
        visitorStatisticsDO.setVisitorDataId(visitorDateId);
        visitorStatisticsDO.setVisitorUserId(param.getUserId());
        visitorStatisticsDO.setVisitorMemberId(param.getMemberId());
        visitorStatisticsDO.setNickname(memberDO.getNickname());
        visitorStatisticsDO.setAvatar(memberDO.getAvatarLocal());
        visitorStatisticsDO.setType(param.getType());
        visitorStatisticsDO.setIp(IpUtils.getIpAddress(request));
        return visitorStatisticsDAO.insert(visitorStatisticsDO);
    }

    @Override
    public DataResultDTO dataResult(Long userId) {
        UserDO user = userDAO.selectById(userId);
        Integer numberVisits = visitorDAO.selectSum(user.getId(), user.getMemberId());
        if (numberVisits == null) {
            numberVisits = 0;
        }
        Integer numberEnterpriseVisits = visitorDateDAO.selectSumByType(user.getId(),2);
        if (numberEnterpriseVisits == null) {
            numberEnterpriseVisits = 0;
        }
        Integer numberJumps = visitorDateDAO.selectSumByType(user.getId(),3);
        if (numberJumps == null) {
            numberJumps = 0;
        }
        Integer numberReturns = visitorDateDAO.selectSumByType(user.getId(),4);
        if (numberReturns == null) {
            numberReturns = 0;
        }
        Integer numberClicks = visitorDateDAO.selectSumByType(user.getId(),5);
        if (numberClicks == null) {
            numberClicks = 0;
        }

        String numberEnterpriseVisitsPercent;
        String numberClicksPercent;

        NumberFormat nf = NumberFormat.getPercentInstance();
        nf.setMinimumFractionDigits(1);//控制保留小数点后几位，2：表示保留2位小数点
        if (numberVisits == 0) {
            numberEnterpriseVisitsPercent = "0.0%";
        } else {
            numberEnterpriseVisitsPercent = nf.format(numberEnterpriseVisits / numberVisits);
        }

        if (numberEnterpriseVisits == 0) {
            numberClicksPercent = "0.0%";
        } else {
            numberClicksPercent = nf.format(numberClicks / numberEnterpriseVisits);
        }

        DataResultDTO dataResultDTO = new DataResultDTO();
        dataResultDTO.setNumberClicks(numberClicks);
        dataResultDTO.setNumberEnterpriseVisits(numberEnterpriseVisits);
        dataResultDTO.setNumberVisits(numberVisits);
        dataResultDTO.setNumberJumps(numberJumps);
        dataResultDTO.setNumberReturns(numberReturns);
        dataResultDTO.setNumberClicksPercent(numberClicksPercent);
        dataResultDTO.setNumberEnterpriseVisitsPercent(numberEnterpriseVisitsPercent);
        dataResultDTO.setNumberVisitsPercent("100%");

        dataResultDTO.setToday(getVisitorDataByDay(user.getId(), user.getMemberId(),0));
        dataResultDTO.setDayAgo7(getVisitorDataByDay(user.getId(), user.getMemberId(),7));
        dataResultDTO.setDayAgo14(getVisitorDataByDay(user.getId(), user.getMemberId(),14));
        return dataResultDTO;
    }

    public List<DataResultDTO.VisitorDataByWeekBean> getVisitorDataByDay(Long userId,Long memberId, Integer day) {
        List<DataResultDTO.VisitorDataByWeekBean> beanList = new LinkedList<>();
        //获取七天内日期
        String [] dateStringArr = DateTimeUtils.getBeforeSevenDay(day);
        for (int i = 0; i < dateStringArr.length; i++) {
            DataResultDTO.VisitorDataByWeekBean bean = new DataResultDTO.VisitorDataByWeekBean();
            String endAt = dateStringArr[i] + " 23:59:59";
            String beginAt = dateStringArr[i] + " 00:00:00";
            Date beginTime = DateTimeUtils.formatDate(beginAt,DateTimeUtils.DATE_TIME_STYLE);
            Date endTime = DateTimeUtils.formatDate(endAt,DateTimeUtils.DATE_TIME_STYLE);

            bean.setFormat(DateTimeUtils.formatString(beginTime,"MM.dd"));
            bean.setTime01((float) 0);
            bean.setTime02((float) 0);

            //去除掉自己访问的时间
            List<VisitorListDO> visitorListDOList = visitorListDAO.selectByUserIdAndData(userId,beginTime,endTime,memberId);
            int totalTime = 0;
            if (visitorListDOList != null && visitorListDOList.size() > 0) {
                //获取所有访客数量
                List<Long> visitorIdList = new LinkedList<>();
                for (VisitorListDO visitorListDO : visitorListDOList) {
                    totalTime += visitorListDO.getTime();
                    visitorIdList.add(visitorListDO.getVisitorMemberId());
                }
                if (totalTime > 0) {
                    List<Long> visitorIdList2 = visitorIdList.stream().distinct().collect(Collectors.toList());
                    //未去重的访客数
                    int allNum = visitorIdList.size();
                    if (allNum > 0) {
                        bean.setTime02(NumberUtils.divide(totalTime,allNum,2));
                    }
                    //去重的访客数
                    int deWeightNum = visitorIdList2.size();
                    if (deWeightNum > 0) {
                        bean.setTime01(NumberUtils.divide(totalTime,deWeightNum,2));
                    }
                }
            }

            beanList.add(bean);
        }

        return beanList;
    }
}
